def make_output(fileformat, datasets, dbname, alleletype, mapcol, destdir, jobs, shard, test, recreate):
    import sys, os, traceback
    sys.path.append("..")
    from sqlalchemy.orm import scoped_session, sessionmaker
    from dbutils import get_db_type
    from output import return_db_layout, write_map_file_single, write_map_file_shard, write_ped_file_single, write_ped_file_shard, write_tped_file_single, write_tfam_file_single
    from utils import get_conf, pg_url, randstr
    conf = get_conf()
    dbuser = conf["dbuser"]
    password = conf["password"]
    portnum = conf["portnum"]
    usr = os.popen('whoami').read().strip()
    dbstring_usr = "%s://%s@:%s/postgres"%(pg_url(), usr, portnum)
    dbstring = "%s://%s:%s@localhost:%s/postgres"%(pg_url(), dbuser, password, portnum)
    dbstring_dbname = "%s://%s:%s@localhost:%s/%s"%(pg_url(), dbuser, password, portnum, dbname)
    from dbutils import get_db_type
    from dbutils import dbuser_exists, db_exists, schema_exists
    from utils import create_engine_wrapper
    db_usr = create_engine_wrapper(dbstring_usr)
    db = create_engine_wrapper(dbstring)
    db_dbname = create_engine_wrapper(dbstring_dbname)
    usr = os.popen('whoami').read().strip()

    if not dbuser_exists(db_usr, dbuser):
        sys.exit("dbuser '%s' does not exist\nrun the init_db.py script, exiting"%dbuser)
    if not db_exists(db, dbname):
        sys.exit("database '%s' does not exist\nrun the init_db.py script, exiting"%dbname)
    dbtype = get_db_type(dbstring_dbname)
    if dbtype not in conf.sections:
        sys.exit("dbtype must be one of %s, not %s.\nWas the database %s created with init_db.py?"%(', '.join(conf.sections), dbtype, dbstring_dbname))
    if alleletype=="forward" or alleletype=="top":
        if dbtype!="illumina":
            sys.exit("alleletype argument of 'forward' or 'top' not valid for dbtype %s"%dbtype)
    if alleletype==None:
        if dbtype!="affy6":
            sys.exit("alleletype argument of 'None' not valid for dbtype %s"%dbtype)
    rstr = randstr()
    if shard and test:
        schemas = [s+'_shard_test' for s in datasets]
    elif shard:
        schemas = [s+'_shard' for s in datasets]
    elif test:
        schemas = [s+'_test' for s in datasets]
    else:
        schemas = datasets
    sm = '-'.join(schemas)

    known_datasets = conf[dbtype].sections
    known_schemas = known_datasets + [s+'_test' for s in known_datasets] + [s+'_shard' for s in known_datasets] + [s+'_shard_test' for s in known_datasets]
    for dataset, schema in zip(datasets, schemas):
        if dataset not in known_datasets:
            sys.exit("error, dataset %s is not listed in the config as one of the datasets associated with database type %s"%(dataset, dbtype))
        if not schema_exists(db_dbname, schema):
            sys.exit("schema '%s' does not exist, exiting"%schema)

    layout = return_db_layout(dbstring_dbname, schemas)
    if layout == 'geno_single':
        shard = False
    elif layout == 'geno_shard':
        shard = True

    sm = '-'.join(schemas)
    filenamedict = {}
    if alleletype == None:
        filenamedict['ped'] =  "%s.%s.ped"%(dbname, sm)
        filenamedict['tped'] = "%s.%s.tped"%(dbname, sm)
    else:
        filenamedict['ped'] =  "%s.%s.%s.ped"%(dbname, sm, alleletype)
        filenamedict['tped'] = "%s.%s.%s.tped"%(dbname, sm, alleletype)
    filenamedict['map'] =  "%s.%s.map"%(dbname, sm)
    filenamedict['tfam'] = "%s.%s.tfam"%(dbname, sm)
    if destdir:
        pass
    elif 'destdir' in conf:
        destdir = conf['destdir']
    else:
        destdir = "."
    for f in filenamedict:
        filenamedict[f] = os.path.abspath(os.path.join(destdir, filenamedict[f]))
    if fileformat in filenamedict:
        filename = filenamedict[fileformat]
    else:
        sys.exit("fileformat name %s not recognized"%fileformat)

    if recreate == True and os.path.exists(filename):
            os.remove(filename)
    else:
        pass

    print "using schemas %s"%', '.join(schemas)

    db = create_engine_wrapper(dbstring_dbname)
    Session = scoped_session(sessionmaker())
    Session.configure(bind=db)

    if fileformat == 'map':
        if shard:
            fn = write_map_file_shard
            args = Session, dbstring_dbname, filename, alleletype, schemas, rstr, mapcol
        else:
            fn = write_map_file_single
            args = Session, dbstring_dbname, filename, alleletype, schemas, rstr, mapcol
    elif fileformat == 'ped':
        if shard:
            fn = write_ped_file_shard
            args = Session, dbstring_dbname, filename, alleletype, jobs, schemas, rstr
        else:
            fn = write_ped_file_single
            args = Session, dbstring_dbname, filename, alleletype, jobs, schemas, rstr
    elif fileformat == 'tped':
        if shard:
            sys.exit("tped file format not supported for shard option")
        else:
            fn = write_tped_file_single
            args = Session, dbstring_dbname, filename, alleletype, jobs, schemas, rstr
    elif fileformat == 'tfam':
        if shard:
            sys.exit("tfam file format not supported for shard option")
        else:
            fn = write_tfam_file_single
            args = Session, dbstring_dbname, filename,  schemas, rstr
    else:
        sys.exit("fileformat name %s not recognized"%fileformat)
    try:
        fn(*args) # run the command
    finally:
        Session.close()
        db.dispose()
        tmpdir = os.path.join(conf["tmpdir"], 'tmp_%s'%rstr)
        if os.path.isdir(tmpdir):
            import shutil
            shutil.rmtree(tmpdir)
        sm = '_'.join(schemas) + '_merge' + '_' + rstr
        db_dbname = create_engine_wrapper(dbstring_dbname)
        conn = db_dbname.connect()
        conn.execute("DROP SCHEMA IF EXISTS %(sm)s CASCADE;"%{'sm':sm})
        for schema in schemas:
            schema_filter = schema+'_filter' + '_' + rstr
            conn.execute("DROP SCHEMA IF EXISTS %(schema_filter)s CASCADE;"%{'schema_filter':schema_filter})
        conn.close()
        db_dbname.dispose()

if __name__=='__main__':
    import sys
    from optparse import OptionParser
    usage = "usage is of the form '%prog [-a alleletype] [-c] [-d destdir] [-j number_of_jobs] [-s] [-t] [-y] fileformat dataset_1 ... dataset_k dbname'\n" \
            + "choices for fileformat are %s"%(', '.join(["map", "ped", "tfam", "tped", "pheno"]))
    parser = OptionParser(usage=usage)
    parser.add_option("-a", "--allele-type", action="store", dest="alleletype",
                      help="allele type (required only for illumina ped and tped fileformats): options are forward or top")
    parser.add_option("-c", "--map-col", action="store_true", dest="mapcol", help="add column to map file")
    parser.add_option("-d", "--destdir", action="store", type="string", dest="destdir", help="destination directory")
    parser.add_option("-j", "--jobs", action="store", type="int", dest="jobs", help="number of jobs to run in parallel. Default is 1", default=1)
    parser.add_option("-s", "--sharding", action="store_true", dest="shard", help="use geno table sharding")
    parser.add_option("-t", "--test", action="store_true", dest="test", default=False, help="test cases")
    parser.add_option("-y", "--recreate", action="store_true", dest="recreate", help="delete schema and recreate")
    (options, args) = parser.parse_args()

    if len(args) < 3:
        print "incorrect number of arguments"
        parser.print_help()
        sys.exit()

    fileformat = args[0]
    datasets = []
    for i, s in enumerate(args):
        if i > 0 and i < len(args)-1:
            datasets.append(s)
    dbname = args[-1]

    make_output(fileformat, datasets, dbname, options.alleletype, options.mapcol, options.destdir, options.jobs, options.shard, options.test, options.recreate)
